package com.flute.framework.autoprompt;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.flute.framework.monitor.EventLogger;
import com.flute.tools.data.DataIterator;
import com.flute.tools.data.DataRecord;
import com.flute.tools.timer.FlexTimer;

/**
 * 为适应新的前缀提示的需要，实现按时间更新需要
 * @author REAMY
 *
 */
public class DefaultAutoPromptMantian extends AutoPromptMantian {
	private ITokenDataProvider provider;
	private int updateInterval;
	private ITrainningTokenBuilder builder;
	private volatile boolean initializing;
	private volatile boolean running;

	public ITrainningTokenBuilder getBuilder() {
		return this.builder;
	}

	public void setBuilder(ITrainningTokenBuilder builder) {
		this.builder = builder;
	}

	public int getUpdateInterval() {
		return this.updateInterval;
	}

	public void setUpdateInterval(int updateInterval) {
		this.updateInterval = updateInterval;
	}

	public void start() {
		if (!(this.running)) {
			this.initializing = true;
			this.running = true;
			initial();
			if (this.updateInterval == 0)
				this.updateInterval = 100000;

			FlexTimer.getInstance().startTimer("update-prompt", this, "update",
					this.updateInterval, true);
		}
	}

	public ITokenDataProvider getProvider() {
		return this.provider;
	}

	public void setProvider(ITokenDataProvider provider) {
		this.provider = provider;
	}

	public void update() throws InterruptedException {
		EventLogger.startNewEvent(AutoPromptMonitor.getUpdateKey());
		/*DataRecordLogger dataLogger = DataRecordLogger.getLogger(EventLogger
				.getCurrentEventId(AutoPromptMonitor.getUpdateKey()));*/
		while (this.initializing) {
			EventLogger
					.info("正在初始化，等待10s...", AutoPromptMonitor.getUpdateKey());
			Thread.sleep(10000L);
		}
		EventLogger.info("开始更新自动提示...", AutoPromptMonitor.getUpdateKey());
		checkWriting();
		this.provider.beginUpdate();
		DataIterator<TokenData> initialIt = this.provider
				.getInitialTokenDatas();

		EventLogger.info("开始'update'自动提示的数据...", AutoPromptMonitor
				.getUpdateKey());
		DataIterator<TokenData> updateIt = this.provider.getUpdateTokenDatas();
		Map<String, Set<String>> dataSet = new HashMap<String, Set<String>>();
		updateIt.reset();
		int count = 0;
		while (updateIt.hasNext()) {
			TokenData td = (TokenData) updateIt.next();
			if (td == null)
				continue;
			DataRecord dr = td.toDataRecord();
			dr.AddField("action", td.getRecordOperator());
			//dataLogger.recordInfo(dr);
			add(td);
			initialIt.reset();
			update(td, dataSet);
			initialIt.reset();
			delete(td, dataSet);
			++count;
		}
		EventLogger.info("'update'自动提示结束,整理索引", AutoPromptMonitor
				.getUpdateKey());
		initialIt.reset();
		AutoPrompt.getInstance().againSortOut(initialIt, dataSet, this.builder);
		updateIt.reset();
		updateIt.close();
		EventLogger.info("'update'自动提示结束,'update'条数为'" + count + "'.",
				AutoPromptMonitor.getUpdateKey());
		initialIt.reset();
		initialIt.close();
		this.provider.endUpdate();
		EventLogger.info("自动提示的更新过程结束.", AutoPromptMonitor.getUpdateKey());
	}

	public void add(TokenData td) {
		if ("add".equals(td.getRecordOperator()))
			AutoPrompt.getInstance().train(td, this.builder);
	}

	public void update(TokenData td, Map<String, Set<String>> map) {
		if ("update".equals(td.getRecordOperator()))
			AutoPrompt.getInstance().update(td, this.builder, map);
	}

	public void delete(TokenData td, Map<String, Set<String>> map) {
		if ("delete".equals(td.getRecordOperator()))
			AutoPrompt.getInstance().delete(td, this.builder, map);
	}

	private void checkWriting() {
		while (this.provider.isWriting()) {
			EventLogger.info("自动提示数据正在写入，等待5秒...", AutoPromptMonitor
					.getUpdateKey());
			try {
				Thread.sleep(5000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void initial() {
		EventLogger.startNewEvent(AutoPromptMonitor.getInitialKey());
		checkWriting();
		Thread th = new Thread(getRunnable());
		th.start();
	}

	private Runnable getRunnable() {
		return new Runnable() {

			@Override
			public void run() {
				EventLogger.info("自动提示开始初始化...", AutoPromptMonitor
						.getInitialKey());
				provider.beginInital();
				DataIterator<TokenData> it = provider.getInitialTokenDatas();

				int count = 0;
				ITrainningTokenBuilder builder = new DefaultTrainingTokenBuilder();
				while (it.hasNext()) {
					TokenData token = it.next();
					if (count++ % 10000 == 0) {
						EventLogger.info("train:" + count, AutoPromptMonitor
								.getInitialKey());
					}
					if (token != null) {
						AutoPrompt.getInstance().train(token, builder);
					}
				}
				EventLogger.info("train done, count:" + count,
						AutoPromptMonitor.getInitialKey());
				it.close();
				provider.endInitial();

				EventLogger
						.info("自动提示初始化结束", AutoPromptMonitor.getInitialKey());
				EventLogger.endEvent(EventLogger
						.getCurrentEventId(AutoPromptMonitor.getInitialKey()));
				initializing = false;
			}

		};
	}
}